package com.unipay.spring.aop.annotation;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @BelongsProject: SSM
 * @Author: cmy
 * @CreateTime: 2023-01-17  13:45
 * @Description: TODO
 */

@Component
@Aspect     // 将当前组件，标注为切面
public class LoggerAspect {

    // 切入点表达式的重用
    @Pointcut("execution(* com.unipay.spring.aop.annotation.CalculatorImpl.*(..))")
    public void pointCut(){}


//    @Before("execution(public int com.unipay.spring.aop.annotation.CalculatorImpl.add(int, int ))")
//    @Before("execution(* com.unipay.spring.aop.annotation.CalculatorImpl.*(..))")
    @Before("pointCut()")
    public void before(JoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        Object[] args = joinPoint.getArgs();
        System.out.println("前置通知...，方法：" + signature + "，参数列表：" + Arrays.toString(args));
    }

    @After("pointCut()")
    public void after(JoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        Object[] args = joinPoint.getArgs();
        System.out.println("后置通知...，方法：" + signature.getName());
    }

    @AfterReturning(value = "pointCut()", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result){
        Signature signature = joinPoint.getSignature();
        Object[] args = joinPoint.getArgs();
        System.out.println("返回通知...，方法：" + signature.getName() + "，结果：" + result);
    }

    @AfterThrowing(value = "pointCut()", throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, Exception e){
        Signature signature = joinPoint.getSignature();
        Object[] args = joinPoint.getArgs();
        System.out.println("异常通知...，方法：" + signature.getName() + "，异常信息：" + e);
    }


    @Around(value = "pointCut()")
    public Object round(ProceedingJoinPoint joinPoint){
        Object res = null;
        try {
            System.out.println("环绕通知-->目标对象方法执行之前：" + joinPoint.getSignature().getName() + "，参数列表：" + Arrays.toString(joinPoint.getArgs()));
            //TODO 目标方法的执行，目标方法的 “返回值” 一定要返回给外界调用者
            res = joinPoint.proceed();
            System.out.println("环绕通知-->目标对象方法返回值之后：" + res);
        } catch (Throwable e) {
            e.printStackTrace();
            System.out.println("环绕通知-->目标对象方法出现异常时：" + e);
        } finally {
            System.out.println("环绕通知-->目标对象方法执行完：" + joinPoint.getSignature());
        }
        return res;
    }
}
